home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
jade
/
src
/
x11_keys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-09
|
9KB
|
347 lines
/* x11_keys.c -- Event translation for X11
Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
This file is part of Jade.
Jade is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Jade is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jade; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "jade.h"
#include "jade_protos.h"
#include <string.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>
#ifdef SWAP_DELETE_KEYS
# define XK_DELETE XK_BackSpace
# define XK_BACKSPACE XK_Delete
#else
# define XK_DELETE XK_Delete
# define XK_BACKSPACE XK_BackSpace
#endif
_PR void translate_event(u_long *, u_long *, XEvent *);
_PR int cook_key(void *, u_char *, int);
_PR bool lookup_event(u_long *, u_long *, u_char *);
_PR bool lookup_event_name(u_char *, u_long, u_long);
_PR u_long esc_code, esc_mods;
u_long esc_code = XK_Escape, esc_mods = EV_TYPE_KEYBD;
static u_long
translate_mods(u_long mods, unsigned int state)
{
if(state & ShiftMask)
mods |= EV_MOD_SHIFT;
if(state & LockMask)
mods ^= EV_MOD_SHIFT;
if(state & ControlMask)
mods |= EV_MOD_CTRL;
if(state & Mod1Mask)
mods |= EV_MOD_MOD1;
if(state & Mod2Mask)
mods |= EV_MOD_MOD2;
if(state & Mod3Mask)
mods |= EV_MOD_MOD3;
if(state & Mod4Mask)
mods |= EV_MOD_MOD4;
if(state & Mod5Mask)
mods |= EV_MOD_MOD5;
if(state & Button1Mask)
mods |= EV_MOD_BUTTON1;
if(state & Button2Mask)
mods |= EV_MOD_BUTTON2;
if(state & Button3Mask)
mods |= EV_MOD_BUTTON3;
if(state & Button4Mask)
mods |= EV_MOD_BUTTON4;
if(state & Button5Mask)
mods |= EV_MOD_BUTTON5;
return(mods);
}
void
translate_event(u_long *code, u_long *mods, XEvent *xev)
{
static Time LastClick;
switch(xev->type)
{
case KeyPress:
*mods = translate_mods(*mods, xev->xkey.state);
if(*mods & EV_MOD_SHIFT)
{
/* Some keys don't have keysym at index 1, if not treat it as
normal keysym shifted. */
*code = XKeycodeToKeysym(x11_display, xev->xkey.keycode, 1);
if(*code == NoSymbol)
*code = XKeycodeToKeysym(x11_display, xev->xkey.keycode, 0);
else
*mods &= ~EV_MOD_SHIFT;
}
else
*code = XKeycodeToKeysym(x11_display, xev->xkey.keycode, 0);
if((*code != NoSymbol) && !IsModifierKey(*code))
*mods |= EV_TYPE_KEYBD;
break;
case ButtonPress:
if(xev->xbutton.time < (LastClick + DOUBLE_CLICK_TIME))
*code = EV_CODE_MOUSE_CLICK2;
else
*code = EV_CODE_MOUSE_CLICK1;
LastClick = xev->xbutton.time;
goto button;
break;
case ButtonRelease:
*code = EV_CODE_MOUSE_UP;
button:
*mods = EV_TYPE_MOUSE
| translate_mods(*mods, xev->xbutton.state);
switch(xev->xbutton.button)
{
case Button1:
*mods |= EV_MOD_BUTTON1;
break;
case Button2:
*mods |= EV_MOD_BUTTON2;
break;
case Button3:
*mods |= EV_MOD_BUTTON3;
break;
case Button4:
*mods |= EV_MOD_BUTTON4;
break;
case Button5:
*mods |= EV_MOD_BUTTON5;
break;
}
break;
}
}
int
cook_key(void *event, u_char *buf, int buflen)
{
XKeyEvent *xk = event;
KeySym ks;
return(XLookupString(xk, buf, buflen, &ks, NULL));
}
/*
* Stuff to translate textual key descriptions into key codes
*/
typedef struct
{
u_char *kd_Name;
u_long kd_Mods;
u_long kd_Code;
} KeyDesc;
static const KeyDesc KeyDescr[] =
{
"Shift", EV_MOD_SHIFT, 0,
"SFT", EV_MOD_SHIFT, 0,
"Ctrl", EV_MOD_CTRL, 0,
"Control", EV_MOD_CTRL, 0,
"CTL", EV_MOD_CTRL, 0,
"Meta", EV_MOD_META, 0,
"Mod1", EV_MOD_MOD1, 0,
"Mod2", EV_MOD_MOD2, 0,
"Amiga", EV_MOD_MOD2, 0,
"Mod3", EV_MOD_MOD3, 0,
"Mod4", EV_MOD_MOD4, 0,
"LMB", EV_MOD_LMB, 0,
"Button1", EV_MOD_BUTTON1, 0,
"MMB", EV_MOD_MMB, 0,
"Button2", EV_MOD_BUTTON2, 0,
"RMB", EV_MOD_RMB, 0,
"Button3", EV_MOD_BUTTON3, 0,
"Button4", EV_MOD_BUTTON4, 0,
"Button5", EV_MOD_BUTTON5, 0,
"SPC", EV_TYPE_KEYBD, XK_space,
"Space", EV_TYPE_KEYBD, XK_space,
"Spacebar", EV_TYPE_KEYBD, XK_space,
"TAB", EV_TYPE_KEYBD, XK_Tab,
"RET", EV_TYPE_KEYBD, XK_Return,
"Return", EV_TYPE_KEYBD, XK_Return,
"ESC", EV_TYPE_KEYBD, XK_Escape,
"Escape", EV_TYPE_KEYBD, XK_Escape,
"BS", EV_TYPE_KEYBD, XK_BACKSPACE,
"Backspace", EV_TYPE_KEYBD, XK_BACKSPACE,
"DEL", EV_TYPE_KEYBD, XK_DELETE,
"Delete", EV_TYPE_KEYBD, XK_DELETE,
"Help", EV_TYPE_KEYBD, XK_Help,
"Up", EV_TYPE_KEYBD, XK_Up,
"Down", EV_TYPE_KEYBD, XK_Down,
"Right", EV_TYPE_KEYBD, XK_Right,
"Left", EV_TYPE_KEYBD, XK_Left,
/* X defines lots of long names for these simple keys... */
" ", EV_TYPE_KEYBD, XK_space,
"!", EV_TYPE_KEYBD, XK_exclam,
"\"", EV_TYPE_KEYBD, XK_quotedbl,
"#", EV_TYPE_KEYBD, XK_numbersign,
"$", EV_TYPE_KEYBD, XK_dollar,
"%", EV_TYPE_KEYBD, XK_percent,
"&", EV_TYPE_KEYBD, XK_ampersand,
"'", EV_TYPE_KEYBD, XK_quoteright,
"(", EV_TYPE_KEYBD, XK_parenleft,
")", EV_TYPE_KEYBD, XK_parenright,
"*", EV_TYPE_KEYBD, XK_asterisk,
"+", EV_TYPE_KEYBD, XK_plus,
",", EV_TYPE_KEYBD, XK_comma,
"-", EV_TYPE_KEYBD, XK_minus,
".", EV_TYPE_KEYBD, XK_period,
"/", EV_TYPE_KEYBD, XK_slash,
":", EV_TYPE_KEYBD, XK_colon,
";", EV_TYPE_KEYBD, XK_semicolon,
"<", EV_TYPE_KEYBD, XK_less,
"=", EV_TYPE_KEYBD, XK_equal,
">", EV_TYPE_KEYBD, XK_greater,
"?", EV_TYPE_KEYBD, XK_question,
"@", EV_TYPE_KEYBD, XK_at,
"[", EV_TYPE_KEYBD, XK_bracketleft,
"\\", EV_TYPE_KEYBD, XK_backslash,
"]", EV_TYPE_KEYBD, XK_bracketright,
"^", EV_TYPE_KEYBD, XK_asciicircum,
"_", EV_TYPE_KEYBD, XK_underscore,
"`", EV_TYPE_KEYBD, XK_quoteleft,
"{", EV_TYPE_KEYBD, XK_braceleft,
"|", EV_TYPE_KEYBD, XK_bar,
"}", EV_TYPE_KEYBD, XK_braceright,
"~", EV_TYPE_KEYBD, XK_asciitilde,
"£", EV_TYPE_KEYBD, XK_sterling,
/* Mouse events */
"Click1", EV_TYPE_MOUSE, EV_CODE_MOUSE_CLICK1,
"Click2", EV_TYPE_MOUSE, EV_CODE_MOUSE_CLICK2,
"Off", EV_TYPE_MOUSE, EV_CODE_MOUSE_UP,
"Move", EV_TYPE_MOUSE, EV_CODE_MOUSE_MOVE,
NULL, 0, 0
};
/* Puts the integers defining the event described in DESC into CODE and
MODS. */
bool
lookup_event(u_long *code, u_long *mods, u_char *desc)
{
u_char *str = desc;
bool rc = TRUE;
*code = *mods = 0;
for(;;)
{
u_char buff[100];
u_char *tmp = buff;
u_char c = *str++;
const KeyDesc *kd = KeyDescr;
/* Get this one token. The first character is read separately to
allow minus characters to be used to represent itself as well as
to terminate a token. */
if(c != 0)
{
*tmp++ = c;
while((c = *str) && (c != '-'))
{
*tmp++ = c;
str++;
}
}
else
goto error;
*tmp = 0;
if(*str)
str++;
while(kd->kd_Name)
{
if(!strcasecmp(kd->kd_Name, buff))
{
*mods |= kd->kd_Mods;
*code = kd->kd_Code;
if(*mods & EV_TYPE_MASK)
goto end;
break;
}
kd++;
}
if(!kd->kd_Name)
{
unsigned int ks;
if((ks = XStringToKeysym(buff)) != NoSymbol)
{
*mods |= EV_TYPE_KEYBD;
*code = ks;
goto end;
}
else
{
error:
cmd_signal(sym_bad_event_desc, LIST_1(string_dup(desc)));
rc = FALSE;
goto end;
}
}
}
end:
return(rc);
}
/* Constructs the name of the event defined by CODE and MODS in BUF. */
bool
lookup_event_name(u_char *buf, u_long code, u_long mods)
{
/* First resolve all modifiers */
u_long tmp_mods = mods & EV_MOD_MASK;
const KeyDesc *kd = KeyDescr;
u_char *name;
while(kd->kd_Name && (tmp_mods != 0))
{
if((tmp_mods & kd->kd_Mods) != 0)
{
tmp_mods &= ~kd->kd_Mods;
buf = stpcpy(buf, kd->kd_Name);
*buf++ = '-';
}
kd++;
}
if(tmp_mods != 0)
return(FALSE);
/* Now try to find the code in our lookup table */
tmp_mods = mods & EV_TYPE_MASK;
#if 0
/* Since all modifiers are at the start of the table this is
unnecessary :-) */
kd = KeyDescr;
#endif
while(kd->kd_Name)
{
if((kd->kd_Mods == tmp_mods) && (kd->kd_Code == code))
{
strcpy(buf, kd->kd_Name);
return(TRUE);
}
kd++;
}
/* Couldn't find it here; have to go to the window-system. */
name = XKeysymToString((KeySym)code);
if(name)
{
strcpy(buf, name);
return(TRUE);
}
return(FALSE);
}